﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using WiseLinkWPF.Windows.Controls;
using System.Collections;

namespace CCF20Module
{

    public enum TextBoxTypes { Standard = 0, NumericOnly = 1, LettersOnly = 2, Masked = 3, CheckBox = 4, ComboBox = 5, DateTime = 6, TextBlock = 7 };
    public enum UpdateTrigger { PropertyChanged = 0, LostFocus = 1 };


    /// <summary>
    /// Represents a single Textbox bound to a CLR object 
    /// property
    /// </summary>
    public partial class CLRObjectBoundTextBox : UserControl
    {
        #region Data
        private string boundPropertyName;
        private string labelToDisplay;
        private TextBoxTypes textBoxTypeToUse = TextBoxTypes.Standard;
        private TextBox txtBoxInUse = null;
        private TextBlock txtBlock = null;
        private CheckBox txtCheckBox = null;
        private RadDatePicker txtDateTimePicker = null;
        private RadComboBox txtComboBox = null;
        private IValueConverter valueConverter = null;

        //private Style inputStyle = null;
        private UpdateSourceTrigger updateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        private string mask = "(999)";
        #endregion



        #region Ctor
        public CLRObjectBoundTextBox()
        {
            InitializeComponent();

            //Get Style for whatever textbox we end up using


            //hook up the DataContextChanged, which will allow the validation to 
            //work when a new bound object is seen
            this.DataContextChanged +=
                new DependencyPropertyChangedEventHandler(CLRObjectBoundTextBox_DataContextChanged);

        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Bind the textbox to the CLR object property, it is assumed that
        /// there is a DataContext that is active that this control will be
        /// using for the binding source
        /// </summary>
        private void CLRObjectBoundTextBox_DataContextChanged(object sender,
            DependencyPropertyChangedEventArgs e)
        {

            Binding bind = new Binding();
            if (this.BindingElementName == null)
            {
                bind.Source = this.DataContext;
            }
            bind.Path = new PropertyPath(BoundPropertyName);
            bind.Mode = BindingMode.TwoWay;
            bind.UpdateSourceTrigger = updateSourceTrigger;
            bind.ValidatesOnDataErrors = true;
            bind.ValidatesOnExceptions = true;





            if (valueConverter != null)
                bind.Converter = valueConverter;

            if (txtBlock != null)
            {
                //clear validation because it is not automatically cleared
                var exp = txtBlock.GetBindingExpression(TextBlock.TextProperty);
                if (exp != null)
                    Validation.ClearInvalid(txtBlock.GetBindingExpression(TextBlock.TextProperty));
                BindingOperations.ClearAllBindings(txtBlock);
                txtBlock.SetBinding(TextBlock.TextProperty, bind);

            }
            else if (txtBoxInUse != null)
            {
                //clear validation because it is not automatically cleared
                var exp = txtBoxInUse.GetBindingExpression(TextBox.TextProperty);
                if (exp != null)
                    Validation.ClearInvalid(txtBoxInUse.GetBindingExpression(TextBox.TextProperty));
                BindingOperations.ClearAllBindings(txtBoxInUse);
                txtBoxInUse.SetBinding(TextBox.TextProperty, bind);

                if (readOnlyBoundPropertyName != null)
                {
                    Binding bindIsReadonly = new Binding();
                    if (this.BindingElementName == null)
                    {
                        bindIsReadonly.Source = this.DataContext;
                    }
                    bindIsReadonly.Path = new PropertyPath(readOnlyBoundPropertyName);
                    bindIsReadonly.Mode = BindingMode.TwoWay;
                    bindIsReadonly.UpdateSourceTrigger = updateSourceTrigger;
                    bindIsReadonly.ValidatesOnDataErrors = true;
                    bindIsReadonly.ValidatesOnExceptions = true;
                    txtBoxInUse.SetBinding(TextBox.IsReadOnlyProperty, bindIsReadonly);
                }

            }
            else if (txtCheckBox != null)
            {
                BindingOperations.ClearAllBindings(txtCheckBox);
                txtCheckBox.SetBinding(CheckBox.IsCheckedProperty, bind);
            }
            else if (txtDateTimePicker != null)
            {
                BindingOperations.ClearAllBindings(txtDateTimePicker);
                txtDateTimePicker.SetBinding(RadDateTimePicker.SelectedDateProperty, bind);
            }
            else if (txtComboBox != null)
            {
                BindingOperations.ClearAllBindings(txtComboBox);
                if (BindingElementName != null)
                {
                    bind.ElementName = BindingElementName;
                    txtComboBox.ItemsSource = this.FindResource(this.MyItemsSource) as IEnumerable;
                }
                else
                {
                    bind.Source = this.FindResource(this.MyItemsSource);
                }
                txtComboBox.SetBinding(RadComboBox.SelectedItemProperty, bind);
            }
        }
        #endregion

        #region Public Properties

        /// <summary>
        /// The underlying objects property to use for the Binding
        /// </summary>
        public string BoundPropertyName
        {
            get { return boundPropertyName; }
            set { boundPropertyName = value; }
        }

        private string readOnlyBoundPropertyName;
        public string ReadOnlyBoundPropertyName
        {
            get { return readOnlyBoundPropertyName; }
            set { readOnlyBoundPropertyName = value; }
        }
        /// <summary>
        /// The Mask to use in case of TextBoxTypes.Masked
        /// </summary>
        public string Mask
        {
            private get { return mask; }
            set
            {
                mask = value;
                if (txtBoxInUse is MaskedTextBox)
                    (txtBoxInUse as MaskedTextBox).Mask = mask;
            }
        }

        /// <summary>
        /// Sets/Gets the Text Box type to use
        /// </summary>
        public TextBoxTypes TextBoxTypeToUse
        {
            private get { return textBoxTypeToUse; }
            set
            {
                textBoxTypeToUse = value;

                switch (textBoxTypeToUse)
                {

                    case TextBoxTypes.TextBlock:
                        txtBlock = new TextBlock();
                        break;
                    case TextBoxTypes.ComboBox:
                        txtComboBox = new RadComboBox();
                        break;
                    case TextBoxTypes.DateTime:
                        txtDateTimePicker = new RadDatePicker();
                        break;

                    case TextBoxTypes.CheckBox:
                        txtCheckBox = new CheckBox();
                        break;
                    case TextBoxTypes.Standard:
                        txtBoxInUse = new TextBox();
                        break;
                    case TextBoxTypes.NumericOnly:
                        txtBoxInUse = new NumericOnlyTextBox();
                        break;
                    case TextBoxTypes.LettersOnly:
                        txtBoxInUse = new LettersOnlyTextBox();
                        break;
                    case TextBoxTypes.Masked:
                        txtBoxInUse = new MaskedTextBox();
                        if (Mask != string.Empty)
                            (txtBoxInUse as MaskedTextBox).Mask = Mask;

                        break;
                    default:
                        txtBoxInUse = new TextBox();

                        break;

                }
                if (txtBlock != null)
                {
                    MyGrid.Children.Add(txtBlock);
                    Grid.SetColumn(txtBlock, 1);

                }
                else if (txtBoxInUse != null)
                {
                    MyGrid.Children.Add(txtBoxInUse);
                    Grid.SetColumn(txtBoxInUse, 1);

                }
                else if (txtCheckBox != null)
                {
                    MyGrid.Children.Add(txtCheckBox);
                    Grid.SetColumn(txtCheckBox, 1);


                }
                else if (txtDateTimePicker != null)
                {
                    MyGrid.Children.Add(txtDateTimePicker);
                    Grid.SetColumn(txtDateTimePicker, 1);


                }
                else if (txtComboBox != null)
                {
                    MyGrid.Children.Add(txtComboBox);
                    Grid.SetColumn(txtComboBox, 1);
                    if (ItemTemplate != null)
                    {
                        DataTemplate dt = this.FindResource(this.ItemTemplate) as DataTemplate;
                        if (dt != null)
                        {
                            txtComboBox.ItemTemplate = dt;
                        }
                    }

                }

                //dpMain.Children.Add(txtBoxInUse);
            }
        }

        /// <summary>
        /// Sets/Gets the UpdateTrigger type to use
        /// </summary>
        public UpdateTrigger UpdateDataSourceTrigger
        {
            set
            {
                switch (value)
                {
                    case UpdateTrigger.LostFocus:
                        updateSourceTrigger = UpdateSourceTrigger.LostFocus;
                        break;
                    case UpdateTrigger.PropertyChanged:
                        updateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                        break;
                    default:
                        updateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                        break;
                }
            }
        }

        /// <summary>
        /// Sets/Gets the label to display
        /// </summary>
        public string LabelToDisplay
        {
            get { return labelToDisplay; }
            set
            {
                labelToDisplay = value;
                lbl.Content = labelToDisplay;
            }
        }


        public bool IsReadOnly
        {
            set
            {
                if (value && txtBoxInUse != null)
                {
                    this.txtBoxInUse.IsReadOnly = true;
                }
            }
        }


        public string TextBoxValue
        {
            get
            {
                if (txtBoxInUse != null)
                {
                    return txtBoxInUse.Text.Trim();
                }
                else
                {
                    return null;
                }
            }
        }

        public IValueConverter ValueConverter
        {
            set
            {
                valueConverter = value;
            }
        }

        public string MyItemsSource { get; set; }

        public string BindingElementName { get; set; }
        public string ItemTemplate { get; set; }
        /// <summary>
        /// Sets/Gets the label position
        /// </summary>
        public Style InputStyle
        {
            set
            {

                //inputStyle = value;
                if (txtBlock != null)
                {
                    txtBlock.Style = value;
                }
                else if (txtBoxInUse != null)
                {
                    txtBoxInUse.Style = value;
                }
                else if (txtCheckBox != null)
                {
                    txtCheckBox.Style = value;

                }
                else if (txtDateTimePicker != null)
                {
                    txtDateTimePicker.Style = value;

                }
                else if (txtComboBox != null)
                {

                }
            }
        }
        public Style LableStyle
        {
            set
            {
                if (value != null)
                {
                    this.lbl.Style = value;
                }
            }
        }

        #endregion

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {

        }
    }
}
